package com.sojpt.boot;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.InterceptorManager;
import com.jfinal.config.Routes;
import com.jfinal.config.Routes.Route;
import com.jfinal.core.Action;
import com.jfinal.core.ActionMapping;
import com.jfinal.core.Controller;
import com.jfinal.core.NotAction;

public class SoJptActionMapping extends ActionMapping {

	public SoJptActionMapping(Routes routes) {
		super(routes);
	}

	@Override
	protected void buildActionMapping() {
		mapping.clear();
		Class<?> dc;
		InterceptorManager interMan = InterceptorManager.me();
		for (Routes routes : getRoutesList()) {
		for (Route route : routes.getRouteItemList()) {
			Class<? extends Controller> controllerClass = route.getControllerClass();
			Interceptor[] controllerInters = interMan.createControllerInterceptor(controllerClass);
			
			boolean declaredMethods = routes.getMappingSuperClass()
					? controllerClass.getSuperclass() == Controller.class
					: true;
			
			Method[] methods = (declaredMethods ? controllerClass.getDeclaredMethods() : controllerClass.getMethods());
			for (Method method : methods) {
				if (declaredMethods) {
					if (!Modifier.isPublic(method.getModifiers()))
						continue ;
				} else {
					dc = method.getDeclaringClass();
					if (dc == Controller.class || dc == Object.class)
						continue ;
				}
				
				if (method.getAnnotation(NotAction.class) != null) {
					continue ;
				}
				
				Interceptor[] actionInters = interMan.buildControllerActionInterceptor(routes.getInterceptors(), controllerInters, controllerClass, method);
				String controllerKey = route.getControllerKey();
				
				String methodName = method.getName();
				//获取请求路径
				String actionKey = getMethodRequstMapping(method);
				if (actionKey == null) continue;
				actionKey = controllerKey == null ? getMethodRequstMapping(method) : spellActionKey(controllerKey, getMethodRequstMapping(method));

				Action action = new Action(controllerKey, actionKey, controllerClass, method, methodName, actionInters, route.getFinalViewPath(routes.getBaseViewPath()));
				if (mapping.put(actionKey, action) != null) {
					throw new RuntimeException(buildMsg(actionKey, controllerClass, method));
				}
			}
		}
		}
		routes.clear();
		
		// support url = controllerKey + urlParas with "/" of controllerKey
		Action action = mapping.get("/");
		if (action != null) {
			mapping.put("", action);
		}
	}
	
	private String spellActionKey(String controllerKey, String methodKey) {
		if (!controllerKey.endsWith(SLASH)) {
			controllerKey = controllerKey + SLASH;
		}
		if (methodKey.startsWith(SLASH)) {
			methodKey = methodKey.substring(1);
		}
		return controllerKey + methodKey;
	}
	
	private String getMethodRequstMapping (Method method) {
		
		RequestMapping requestMapping = method.getDeclaredAnnotation(RequestMapping.class);
		if (requestMapping != null) 
			return requestMapping.value()[0];
		
		GetMapping getRequestMothed = method.getDeclaredAnnotation(GetMapping.class);
		if (getRequestMothed != null) 
			return getRequestMothed.value()[0];
		
	    PutMapping putRequestMothed = method.getDeclaredAnnotation(PutMapping.class);
	    if (putRequestMothed != null) 
	    	return putRequestMothed.value()[0];
	    
	    PostMapping postRequestMothed = method.getDeclaredAnnotation(PostMapping.class);
	    if (postRequestMothed != null) 
	    	return postRequestMothed.value()[0];
	    
	    DeleteMapping deleteRequestMothed = method.getAnnotation(DeleteMapping.class);
	    if (deleteRequestMothed != null)
	    	return deleteRequestMothed.value()[0];
		
		return null;
		
	}
	
}
